<!DOCTYPE HTML>
<html lang="zh-CN">

<head>
    <!--Setting-->
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta http-equiv="Cache-Control" content="no-siteapp">
    <meta http-equiv="Cache-Control" content="no-transform">
    <meta name="renderer" content="webkit|ie-comp|ie-stand">
    <meta name="apple-mobile-web-app-capable" content="涛哥的博客">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="format-detection" content="telephone=no,email=no,adress=no">
    <meta name="browsermode" content="application">
    <meta name="screen-orientation" content="portrait">
    <meta name="theme-version" content="1.2.3">
    <meta name="root" content="/">
    <link rel="dns-prefetch" href="https://jaredtao.github.io">
    <!--SEO-->

<meta name="keywords" content="Qt,Qml,QtQuick,特效" />


<meta name="description" content="
简介
源码
效果预览
穿云洞
星球之光
蜗牛
超级马里奥


关于ShaderToy
关于ShaderEffect
ShaderToy原理
约定的变量
glsl版本号
glsl版本兼容
Sha..." />


<meta name="robots" content="all" />
<meta name="google" content="all" />
<meta name="googlebot" content="all" />
<meta name="verify" content="all" />
    <!--Title-->

<title>
    
    玩转Qml(16)-移植ShaderToy |
    
    涛哥的博客
</title>

<link rel="alternate" href="/atom.xml" title="涛哥的博客" type="application/atom+xml">


<link rel="icon" href="/favicon.ico">

    


<link rel="stylesheet" href="/css/bootstrap.min.css?rev=3.3.7.css">
<link rel="stylesheet" href="/css/font-awesome.min.css?rev=4.7.0.css">
<link rel="stylesheet" href="/css/style.css?rev=@@hash.css">

    
<div class="hide">
    <script type="text/javascript">
    var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");
    document.write(unescape("%3Cspan class='cnzz_stat_icon_1263868967 hide' %3E%3Cscript%20src%3D%22https%3A%2F%2Fs95.cnzz.com%2Fz_stat.php%3Fweb_id%3D1272564536%22%3E%3C%2Fscript%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s19.cnzz.com/z_stat.php%3Fid%3D1263868967%26show%3Dpic1' type='text/javascript'%3E%3C/script%3E"));
    </script>
</div>




    

<script>
(function() {
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https') {
        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
    } else {
        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
})();
</script>

<meta name="generator" content="Hexo 4.2.1"></head>
<!--[if lte IE 8]>
<style>
    html{ font-size: 1em }
</style>
<![endif]-->
<!--[if lte IE 9]>
<div style="ie">你使用的浏览器版本过低，为了你更好的阅读体验，请更新浏览器的版本或者使用其他现代浏览器，比如Chrome、Firefox、Safari等。</div>
<![endif]-->
<body>
    <header class="main-header"  style="background-image:url(
    http://snippet.shenliyang.com/img/banner.jpg)"
     >
    <div class="main-header-box">
        <a class="header-avatar" href="/" title='JaredTao'>
            <img src="/img/avatar.jpg" alt="logo头像" class="img-responsive center-block">
        </a>
        <div class="branding">
            <!--<h2 class="text-hide">Snippet主题,从未如此简单有趣</h2>-->
            
            <h2>
                单枪匹马亦对饮，历经磨难记初心
            </h2>
            
        </div>
    </div>
</header>
    <nav class="main-navigation">
    <div class="container">
        <div class="row">
            <div class="col-sm-12">
                <div class="navbar-header"><span class="nav-toggle-button collapsed pull-right" data-toggle="collapse" data-target="#main-menu" id="mnav">
                        <span class="sr-only"></span>
                        <i class="fa fa-bars"></i>
                    </span>
                    <a class="navbar-brand" href="https://jaredtao.github.io">
                        涛哥的博客</a>
                </div>
                <div class="collapse navbar-collapse" id="main-menu">
                    <ul class="menu">
                        
                        <li role="presentation" class="text-center">
                            <a href="/"><i class="fa "></i>
                                首页</a>
                        </li>
                        
                        <li role="presentation" class="text-center">
                            <a href="/categories/玩转Qt/"><i class="fa "></i>
                                玩转Qt</a>
                        </li>
                        
                        <li role="presentation" class="text-center">
                            <a href="/categories/玩转Qml/"><i class="fa "></i>
                                玩转Qml</a>
                        </li>
                        
                        <li role="presentation" class="text-center">
                            <a href="/categories/玩转QtQuick/"><i class="fa "></i>
                                玩转QtQuick</a>
                        </li>
                        
                        <li role="presentation" class="text-center">
                            <a href="/categories/涛哥的博客/"><i class="fa "></i>
                                涛哥的博客</a>
                        </li>
                        
                        <li role="presentation" class="text-center">
                            <a href="/archives/"><i class="fa "></i>
                                时间轴</a>
                        </li>
                        
                    </ul>
                </div>
            </div>
        </div>
    </div>
</nav>
    <section class="content-wrap">
        <div class="container">
            <div class="row">
                <main class="col-md-8 main-content m-post">
                    <p id="process"></p>
<article class="post">
    <div class="post-head">
        <h1 id="玩转Qml(16)-移植ShaderToy">
            
            玩转Qml(16)-移植ShaderToy
            
        </h1>
        <div class="post-meta">
    
    <span class="categories-meta fa-wrap">
        <i class="fa fa-folder-open-o"></i>
        <a class="category-link" href="/categories/%E7%8E%A9%E8%BD%ACQml/">玩转Qml</a>
    </span>
    
    
    <span class="fa-wrap">
        <i class="fa fa-tags"></i>
        <span class="tags-meta">
            
            <a class="tag-link" href="/tags/Qml/" rel="tag">Qml</a> <a class="tag-link" href="/tags/Qt/" rel="tag">Qt</a> <a class="tag-link" href="/tags/QtQuick/" rel="tag">QtQuick</a> <a class="tag-link" href="/tags/%E7%89%B9%E6%95%88/" rel="tag">特效</a>
            
        </span>
    </span>
    
    
    
    <span class="fa-wrap">
        <i class="fa fa-clock-o"></i>
        <span class="date-meta">
            2019/07/04</span>
    </span>
    
    <span class="fa-wrap">
        <i class="fa fa-eye"></i>
        <span id="busuanzi_value_page_pv"></span>
    </span>
    
    
</div>
        
        
        <p class="fa fa-exclamation-triangle warning">
            本文于<strong>
                642</strong>
            天之前发表，文中内容可能已经过时。
        </p>
        
    </div>
    
<div id="post-gallery">
    
    <img src="/img/avatar.jpg" alt="gallery-img" class="gallery">
    
</div>

    <div class="post-body post-content">
        <ul>
<li><a href="#简介">简介</a></li>
<li><a href="#源码">源码</a></li>
<li><a href="#效果预览">效果预览</a><ul>
<li><a href="#穿云洞">穿云洞</a></li>
<li><a href="#星球之光">星球之光</a></li>
<li><a href="#蜗牛">蜗牛</a></li>
<li><a href="#超级马里奥">超级马里奥</a></li>
</ul>
</li>
<li><a href="#关于shadertoy">关于ShaderToy</a></li>
<li><a href="#关于shadereffect">关于ShaderEffect</a></li>
<li><a href="#shadertoy原理">ShaderToy原理</a><ul>
<li><a href="#约定的变量">约定的变量</a></li>
<li><a href="#glsl版本号">glsl版本号</a></li>
<li><a href="#glsl版本兼容">glsl版本兼容</a></li>
<li><a href="#shadertoy适配">ShaderToy适配</a></li>
</ul>
</li>
<li><a href="#taoshadertoy">TaoShaderToy</a></li>
</ul>
<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>这次涛哥将会教大家移植ShaderToy的特效到Qml</p>
<h2 id="源码"><a href="#源码" class="headerlink" title="源码"></a>源码</h2><p>《玩转Qml》系列文章，配套了一个优秀的开源项目:TaoQuick</p>
<p>github <a href="https://github.com/jaredtao/TaoQuick" target="_blank" rel="noopener">https://github.com/jaredtao/TaoQuick</a></p>
<p>访问不了或者速度太慢，可以用国内的镜像网站gitee</p>
<p><a href="https://gitee.com/jaredtao/TaoQuick" target="_blank" rel="noopener">https://gitee.com/jaredtao/TaoQuick</a></p>
<h2 id="效果预览"><a href="#效果预览" class="headerlink" title="效果预览"></a>效果预览</h2><p>先看几个效果图</p>
<h3 id="穿云洞"><a href="#穿云洞" class="headerlink" title="穿云洞"></a>穿云洞</h3><p><img src="/images/ShaderToy/Preview1.gif" alt=""></p>
<h3 id="星球之光"><a href="#星球之光" class="headerlink" title="星球之光"></a>星球之光</h3><p><img src="/images/ShaderToy/Preview2.gif" alt=""></p>
<h3 id="蜗牛"><a href="#蜗牛" class="headerlink" title="蜗牛"></a>蜗牛</h3><p><img src="/images/ShaderToy/Preview3.gif" alt=""></p>
<h3 id="超级马里奥"><a href="#超级马里奥" class="headerlink" title="超级马里奥"></a>超级马里奥</h3><p><img src="/images/ShaderToy/Preview4.gif" alt=""></p>
<p>gif录制质量较低，可编译运行TaoQuick源码或使用涛哥打包好的可执行程序，查看实际运行效果。</p>
<p>可执行程序下载链接(包括windows 和 MacOS平台) <a href="https://github.com/jaredtao/TaoQuick/releases" target="_blank" rel="noopener">https://github.com/jaredtao/TaoQuick/releases</a>  </p>
<h2 id="关于ShaderToy"><a href="#关于ShaderToy" class="headerlink" title="关于ShaderToy"></a>关于ShaderToy</h2><p>学习过计算机图形学的人，都应该知道大名鼎鼎的ShaderToy网站 </p>
<p>用一些Shader代码和简单的纹理，就可以输出各种酷炫的图形效果和音频效果。</p>
<p>如果你还不知道，赶紧去看看吧<a href="https://www.shadertoy.com" target="_blank" rel="noopener">https://www.shadertoy.com</a></p>
<p>顺便提一下，该网站的作者是IQ大神，这里有他的博客：</p>
<p><a href="http://www.iquilezles.org/www/articles/raymarchingdf/raymarchingdf.htm" target="_blank" rel="noopener">http://www.iquilezles.org/www/articles/raymarchingdf/raymarchingdf.htm</a></p>
<p>本文主要讨论图形效果，音频效果以后再实现。</p>
<h2 id="关于ShaderEffect"><a href="#关于ShaderEffect" class="headerlink" title="关于ShaderEffect"></a>关于ShaderEffect</h2><p>Qml中实现ShaderToy，最快的途径就是ShaderEffect了。</p>
<p>上一篇文章《Qml特效-着色器效果ShaderEffect》已经介绍过ShaderEffect了, 本文重点是移植ShaderToy。</p>
<p>在涛哥写这篇文章之前，已经有两位前辈做过相关的研究。</p>
<p>陈锦明： <a href="https://zhuanlan.zhihu.com/p/38942460" target="_blank" rel="noopener">https://zhuanlan.zhihu.com/p/38942460</a></p>
<p>qyvlik: <a href="https://zhuanlan.zhihu.com/p/44417680" target="_blank" rel="noopener">https://zhuanlan.zhihu.com/p/44417680</a></p>
<p>涛哥参考了他们的实现，做了一些改进、完善。</p>
<p>在此感谢两位前辈。</p>
<p>下面正文开始</p>
<h2 id="ShaderToy原理"><a href="#ShaderToy原理" class="headerlink" title="ShaderToy原理"></a>ShaderToy原理</h2><p>OpenGL的可编程渲染管线中，着色器代码是可以动态编译、加载到GPU运行的。</p>
<p>而OpenGL又包括了桌面版(OpenGL Desktop)、嵌入式版(OpenGL ES)以及网页版(WebGL)</p>
<p>ShaderToy网站是以WebGL 2.0为基础，提供内置函数、变量，并约定了一些输入变量，由用户按照约定编写着色器代码。</p>
<p>只要不是太老的OpenGL版本，内置函数、变量基本都是通用的。</p>
<h3 id="约定的变量"><a href="#约定的变量" class="headerlink" title="约定的变量"></a>约定的变量</h3><p>ShaderToy网站约定的变量如下：</p>
<figure class="highlight glsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">vec3</span>        iResolution             image/<span class="keyword">buffer</span>        The viewport resolution (z is pixel aspect ratio, usually <span class="number">1.0</span>)</span><br><span class="line"><span class="type">float</span>       iTime                   image/sound/<span class="keyword">buffer</span>	Current time <span class="keyword">in</span> seconds</span><br><span class="line"><span class="type">float</span>       iTimeDelta              image/<span class="keyword">buffer</span>        Time it takes to render a frame, <span class="keyword">in</span> seconds</span><br><span class="line"><span class="type">int</span>         iFrame                  image/<span class="keyword">buffer</span>        Current frame</span><br><span class="line"><span class="type">float</span>       iFrameRate              image/<span class="keyword">buffer</span>        Number of frames rendered per second</span><br><span class="line"><span class="type">float</span>       iChannelTime[<span class="number">4</span>]         image/<span class="keyword">buffer</span>        Time <span class="keyword">for</span> channel (<span class="keyword">if</span> video or sound), <span class="keyword">in</span> seconds</span><br><span class="line"><span class="type">vec3</span>        iChannelResolution[<span class="number">4</span>]	image/<span class="keyword">buffer</span>/sound	Input <span class="built_in">texture</span> resolution <span class="keyword">for</span> each channel</span><br><span class="line"><span class="type">vec4</span>        iMouse                  image/<span class="keyword">buffer</span>        xy = current pixel coords (<span class="keyword">if</span> LMB is down). zw = click pixel</span><br><span class="line"><span class="type">sampler2D</span>	iChannel&#123;i&#125;             image/<span class="keyword">buffer</span>/sound	Sampler <span class="keyword">for</span> input textures i</span><br><span class="line"><span class="type">vec4</span>        iDate                   image/<span class="keyword">buffer</span>/sound	Year, month, day, time <span class="keyword">in</span> seconds <span class="keyword">in</span> .xyzw</span><br><span class="line"><span class="type">float</span>       iSampleRate             image/<span class="keyword">buffer</span>/sound	The sound <span class="keyword">sample</span> rate (typically <span class="number">44100</span>)</span><br></pre></td></tr></table></figure>

<p>Qml中的相应实现</p>
<figure class="highlight qml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">ShaderEffect</span> &#123;</span><br><span class="line">    <span class="attribute">id:</span><span class="string"> shader</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">//properties for shader</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">//not pass to shader</span></span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> vector3d defaultResolution</span>: Qt.vector3d(shader.width, shader.height, shader.width / shader.height)</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">calcResolution</span>(<span class="params">channel</span>) </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (channel) &#123;</span><br><span class="line">            <span class="keyword">return</span> Qt.vector3d(channel.width, channel.height, channel.width / channel.height);</span><br><span class="line">        &#125; <span class="title">else</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> defaultResolution;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//pass</span></span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> vector3d  iResolution</span>: defaultResolution</span><br><span class="line">    <span class="keyword">property</span><span class="string"> real       iTime</span>: <span class="number">0</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> real       iTimeDelta</span>: <span class="number">100</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> int        iFrame</span>: <span class="number">10</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> real       iFrameRate</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> vector4d   iMouse</span>;</span><br><span class="line">    <span class="keyword">property</span><span class="string"> var iChannel0</span>; <span class="comment">//only Image or ShaderEffectSource</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> var iChannel1</span>; <span class="comment">//only Image or ShaderEffectSource</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> var iChannel2</span>; <span class="comment">//only Image or ShaderEffectSource</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> var iChannel3</span>; <span class="comment">//only Image or ShaderEffectSource</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> var        iChannelTime</span>: [<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line">    <span class="keyword">property</span><span class="string"> var        iChannelResolution</span>: [calcResolution(iChannel0), calcResolution(iChannel1), calcResolution(iChannel2), calcResolution(iChannel3)]</span><br><span class="line">    <span class="keyword">property</span><span class="string"> vector4d   iDate</span>;</span><br><span class="line">    <span class="keyword">property</span><span class="string"> real       iSampleRate</span>: <span class="number">44100</span></span><br><span class="line">    </span><br><span class="line">    ...</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>其中时间、日期通过Timer刷新，鼠标位置用MouseArea刷新。</p>
<p>同时涛哥导出了hoverEnabled、running属性和restart函数，以方便Qml中控制Shader的运行。</p>
<figure class="highlight qml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">ShaderEffect</span> &#123;</span><br><span class="line">    <span class="attribute">id:</span><span class="string"> shader</span></span><br><span class="line">...</span><br><span class="line">    <span class="comment">//properties for Qml controller</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> alias hoverEnabled</span>: mouse.hoverEnabled</span><br><span class="line">    <span class="keyword">property</span><span class="string"> bool running</span>: <span class="literal">true</span></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">restart</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        shader.iTime = <span class="number">0</span></span><br><span class="line">        running = <span class="literal">true</span></span><br><span class="line">        timer1.restart()</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title">Timer</span> &#123;</span><br><span class="line">        <span class="attribute">id:</span><span class="string"> timer1</span></span><br><span class="line">        <span class="attribute">running</span>: shader.running</span><br><span class="line">        <span class="attribute">triggeredOnStart</span>: <span class="literal">true</span></span><br><span class="line">        <span class="attribute">interval</span>: <span class="number">16</span></span><br><span class="line">        <span class="attribute">repeat</span>: <span class="literal">true</span></span><br><span class="line">        <span class="attribute">onTriggered</span>: &#123;</span><br><span class="line">            shader.iTime += <span class="number">0.016</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title">Timer</span> &#123;</span><br><span class="line">        <span class="attribute">running</span>: shader.running</span><br><span class="line">        <span class="attribute">interval</span>: <span class="number">1000</span></span><br><span class="line">        <span class="attribute">onTriggered</span>: &#123;</span><br><span class="line">            <span class="keyword">var</span> <span class="built_in">date</span> = <span class="keyword">new</span> <span class="built_in">Date</span>();</span><br><span class="line">            shader.iDate.x = <span class="built_in">date</span>.getFullYear();</span><br><span class="line">            shader.iDate.y = <span class="built_in">date</span>.getMonth();</span><br><span class="line">            shader.iDate.z = <span class="built_in">date</span>.getDay();</span><br><span class="line">            shader.iDate.w = <span class="built_in">date</span>.getSeconds()</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title">MouseArea</span> &#123;</span><br><span class="line">        <span class="attribute">id:</span><span class="string"> mouse</span></span><br><span class="line">        <span class="attribute">anchors.fill</span>: <span class="built_in">parent</span></span><br><span class="line">        <span class="attribute">onPositionChanged</span>: &#123;</span><br><span class="line">            shader.iMouse.x = mouseX</span><br><span class="line">            shader.iMouse.y = mouseY</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="attribute">onClicked</span>: &#123;</span><br><span class="line">            shader.iMouse.z = mouseX</span><br><span class="line">            shader.iMouse.w = mouseY</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="glsl版本号"><a href="#glsl版本号" class="headerlink" title="glsl版本号"></a>glsl版本号</h3><p>GLSL Versions</p>
<table>
<thead>
<tr>
<th>OpenGL Version</th>
<th>GLSL Version</th>
</tr>
</thead>
<tbody><tr>
<td>2.0</td>
<td>110</td>
</tr>
<tr>
<td>2.1</td>
<td>120</td>
</tr>
<tr>
<td>3.0</td>
<td>130</td>
</tr>
<tr>
<td>3.1</td>
<td>140</td>
</tr>
<tr>
<td>3.2</td>
<td>150</td>
</tr>
<tr>
<td>3.3</td>
<td>330</td>
</tr>
<tr>
<td>4.0</td>
<td>400</td>
</tr>
<tr>
<td>4.1</td>
<td>410</td>
</tr>
<tr>
<td>4.2</td>
<td>420</td>
</tr>
<tr>
<td>4.3</td>
<td>430</td>
</tr>
</tbody></table>
<p>GLSL ES Versions (Android, iOS, WebGL)</p>
<table>
<thead>
<tr>
<th>OpenGL ES Version</th>
<th>GLSL ES Version</th>
</tr>
</thead>
<tbody><tr>
<td>2.0</td>
<td>100</td>
</tr>
<tr>
<td>3.0</td>
<td>300</td>
</tr>
</tbody></table>
<h3 id="glsl版本兼容"><a href="#glsl版本兼容" class="headerlink" title="glsl版本兼容"></a>glsl版本兼容</h3><p>ShaderToy限定了WebGL 2.0，而我们移植到Qml中，自然是希望能够在所有可以运行Qml的设备上运行ShaderToy效果。</p>
<p>所以要做一些glsl版本相关的处理。</p>
<p>涛哥研究了Qt的GraphicsEffects模块源码，它的版本处理要么默认，要么 150 core，显然是不够用的。</p>
<p>glsl各个版本的差异，可以参考这里 <a href="https://github.com/mattdesl/lwjgl-basics/wiki/glsl-versions" target="_blank" rel="noopener">https://github.com/mattdesl/lwjgl-basics/wiki/glsl-versions</a></p>
<p>涛哥总结出了如下的代码和注释说明：</p>
<p>注意”#version  xxx”必须是着色器的第一行，不能换行</p>
<figure class="highlight qml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line">    </span><br><span class="line">    <span class="comment">// 如果环境是OpenGL ES2，默认的version是 version 110, 不需要写出来。</span></span><br><span class="line">    <span class="comment">// 比ES2更老的版本是ES 1.0 和 ES 1.1, 这种古董设备，建议还是不要玩Shader了吧。</span></span><br><span class="line">    <span class="comment">// ES2没有texture函数，要用旧的texture2D代替</span></span><br><span class="line">    <span class="comment">// 精度限定要写成float</span></span><br><span class="line"></span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> string gles2Ver</span>: <span class="string">"</span></span><br><span class="line"><span class="string">#define texture texture2D</span></span><br><span class="line"><span class="string">precision mediump float;</span></span><br><span class="line"><span class="string">"</span></span><br><span class="line">    <span class="comment">// 如果环境是OpenGL ES3，version是 version 300 es</span></span><br><span class="line">    <span class="comment">// ES 3.1 ES 3.2也可以。</span></span><br><span class="line">    <span class="comment">// ES3可以用in out 关键字，gl_FragColor也可以用out fragColor取代</span></span><br><span class="line">    <span class="comment">// 精度限定要写成float</span></span><br><span class="line"></span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> string gles3Ver</span>: <span class="string">"#version 300 es</span></span><br><span class="line"><span class="string">#define varying in</span></span><br><span class="line"><span class="string">#define gl_FragColor fragColor</span></span><br><span class="line"><span class="string">precision mediump float;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">out vec4 fragColor;</span></span><br><span class="line"><span class="string">"</span></span><br><span class="line">    <span class="comment">// 如果环境是OpenGL Desktop 3.x，version这里参考Qt默认的version 150。大部分Desktop设备应该</span></span><br><span class="line">    <span class="comment">// 都是150, 即3.2版本，第一个区分Core和Compatibility的版本。</span></span><br><span class="line">    <span class="comment">// Core是核心模式，只有核心api以减轻负担。相应的Compatibility是兼容模式，保留全部API以兼容低版本。</span></span><br><span class="line">    <span class="comment">// Desktop 3.x 可以用in out 关键字，gl_FragColor也可以用out fragColor取代</span></span><br><span class="line">    <span class="comment">// 精度限定抹掉，用默认的。不抹掉有些情况下会报错，不能通用。</span></span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> string gl3Ver</span>: <span class="string">"#version 150</span></span><br><span class="line"><span class="string">#define varying in</span></span><br><span class="line"><span class="string">#define gl_FragColor fragColor</span></span><br><span class="line"><span class="string">#define lowp</span></span><br><span class="line"><span class="string">#define mediump</span></span><br><span class="line"><span class="string">#define highp</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">out vec4 fragColor;</span></span><br><span class="line"><span class="string">"</span></span><br><span class="line">    <span class="comment">// 如果环境是OpenGL Desktop 2.x，version这里就用2.0的version 110，即2.0版本</span></span><br><span class="line">    <span class="comment">// 2.x 没有texture函数，要用旧的texture2D代替</span></span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> string gl2Ver</span>: <span class="string">"#version 110</span></span><br><span class="line"><span class="string">#define texture texture2D</span></span><br><span class="line"><span class="string">"</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> string versionString</span>: &#123;</span><br><span class="line">        <span class="keyword">if</span> (Qt.platform.os === <span class="string">"android"</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (GraphicsInfo.majorVersion === <span class="number">3</span>) &#123;</span><br><span class="line">                <span class="built_in">console</span>.log(<span class="string">"android gles 3"</span>)</span><br><span class="line">                <span class="keyword">return</span> gles3Ver</span><br><span class="line">            &#125; <span class="title">else</span> &#123;</span><br><span class="line">                <span class="built_in">console</span>.log(<span class="string">"android gles 2"</span>)</span><br><span class="line">                <span class="keyword">return</span> gles2Ver</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="title">else</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (GraphicsInfo.majorVersion === <span class="number">3</span> ||GraphicsInfo.majorVersion === <span class="number">4</span>) &#123;</span><br><span class="line">                <span class="keyword">return</span> gl3Ver</span><br><span class="line">            &#125; <span class="title">else</span> &#123;</span><br><span class="line">                <span class="keyword">return</span> gl2Ver</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> string forwardString</span>: versionString + <span class="string">"</span></span><br><span class="line"><span class="string">        varying vec2 qt_TexCoord0;</span></span><br><span class="line"><span class="string">        varying vec4 vertex;</span></span><br><span class="line"><span class="string">        uniform lowp   float qt_Opacity;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        uniform vec3   iResolution;</span></span><br><span class="line"><span class="string">        uniform float  iTime;</span></span><br><span class="line"><span class="string">        uniform float  iTimeDelta;</span></span><br><span class="line"><span class="string">        uniform int    iFrame;</span></span><br><span class="line"><span class="string">        uniform float  iFrameRate;</span></span><br><span class="line"><span class="string">        uniform float  iChannelTime[4];</span></span><br><span class="line"><span class="string">        uniform vec3   iChannelResolution[4];</span></span><br><span class="line"><span class="string">        uniform vec4   iMouse;</span></span><br><span class="line"><span class="string">        uniform vec4    iDate;</span></span><br><span class="line"><span class="string">        uniform float   iSampleRate;</span></span><br><span class="line"><span class="string">        uniform sampler2D   iChannel0;</span></span><br><span class="line"><span class="string">        uniform sampler2D   iChannel1;</span></span><br><span class="line"><span class="string">        uniform sampler2D   iChannel2;</span></span><br><span class="line"><span class="string">        uniform sampler2D   iChannel3;</span></span><br><span class="line"><span class="string">    "</span></span><br></pre></td></tr></table></figure>
<p>versionString 这里，主要测试了Desktop和 android设备，Desktop只要显卡不太搓，都能运行的。</p>
<p>Android ES3的也是全部支持，ES2的部分不能运行，比如iq大神的蜗牛Shader，使用了textureLod等一系列内置函数，就不能在ES2上面跑。</p>
<h3 id="ShaderToy适配"><a href="#ShaderToy适配" class="headerlink" title="ShaderToy适配"></a>ShaderToy适配</h3><p>本来是不需要写顶点着色器的。如果我们想把ShaderToy做成一个任意坐标开始的Item来用，就需要适配一下坐标。</p>
<p>涛哥写的顶点着色器如下，仅在默认着色器的基础上，传递qt_Vertex给下一阶段的vertex</p>
<figure class="highlight qml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="attribute">vertexShader</span>: <span class="string">"</span></span><br><span class="line"><span class="string">          uniform mat4 qt_Matrix;</span></span><br><span class="line"><span class="string">          attribute vec4 qt_Vertex;</span></span><br><span class="line"><span class="string">          attribute vec2 qt_MultiTexCoord0;</span></span><br><span class="line"><span class="string">          varying vec2 qt_TexCoord0;</span></span><br><span class="line"><span class="string">          varying vec4 vertex;</span></span><br><span class="line"><span class="string">          void main() &#123;</span></span><br><span class="line"><span class="string">              vertex = qt_Vertex;</span></span><br><span class="line"><span class="string">              gl_Position = qt_Matrix * vertex;</span></span><br><span class="line"><span class="string">              qt_TexCoord0 = qt_MultiTexCoord0;</span></span><br><span class="line"><span class="string">          &#125;"</span></span><br></pre></td></tr></table></figure>
<p>片段着色器这里处理一下，适配出一个符合shaderToy的mainImage作为入口函数</p>
<figure class="highlight qml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">readonly <span class="keyword">property</span><span class="string"> string startCode</span>: <span class="string">"</span></span><br><span class="line"><span class="string">    void main(void)</span></span><br><span class="line"><span class="string">    &#123;</span></span><br><span class="line"><span class="string">        mainImage(gl_FragColor, vec2(vertex.x, iResolution.y - vertex.y));</span></span><br><span class="line"><span class="string">    &#125;"</span></span><br><span class="line">readonly <span class="keyword">property</span><span class="string"> string defaultPixelShader</span>: <span class="string">"</span></span><br><span class="line"><span class="string">    void mainImage(out vec4 fragColor, in vec2 fragCoord)</span></span><br><span class="line"><span class="string">    &#123;</span></span><br><span class="line"><span class="string">        fragColor = vec4(fragCoord, fragCoord.x, fragCoord.y);</span></span><br><span class="line"><span class="string">    &#125;"</span></span><br><span class="line"><span class="keyword">property</span><span class="string"> string pixelShader</span>: <span class="string">""</span></span><br><span class="line"><span class="attribute">fragmentShader</span>: forwardString + (pixelShader ? <span class="attribute">pixelShader</span> : defaultPixelShader) + startCode</span><br></pre></td></tr></table></figure>
<p>稍微说明一下，qyvlik大佬的Shader使用gl_FragCoord作为片段坐标传进去了，这种用法的ShaderToy坐标将会占据整个Qml的窗口，</p>
<p>而实际ShaderToy坐标不是整个窗口的时候，超出去的地方就会被切掉，显示出来的只有一小部分。</p>
<p>涛哥研究了一番后，顶点着色器把vertex传过来，vertex.x就是x坐标，vertex.y坐标从上到下是0 - height，而gl_FragCoord 从下到上是0 - height，</p>
<p>所以要翻一下。</p>
<h2 id="TaoShaderToy"><a href="#TaoShaderToy" class="headerlink" title="TaoShaderToy"></a>TaoShaderToy</h2><p>最后，看一下代码的全貌吧</p>
<figure class="highlight qml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//TaoShaderToy.qml</span></span><br><span class="line"><span class="keyword">import</span> QtQuick <span class="number">2.12</span></span><br><span class="line"><span class="keyword">import</span> QtQuick.Controls <span class="number">2.12</span></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">vec3        iResolution             image/buffer        The viewport resolution (z is pixel aspect ratio, usually 1.0)</span></span><br><span class="line"><span class="comment">float       iTime                   image/sound/buffer	Current time in seconds</span></span><br><span class="line"><span class="comment">float       iTimeDelta              image/buffer        Time it takes to render a frame, in seconds</span></span><br><span class="line"><span class="comment">int         iFrame                  image/buffer        Current frame</span></span><br><span class="line"><span class="comment">float       iFrameRate              image/buffer        Number of frames rendered per second</span></span><br><span class="line"><span class="comment">float       iChannelTime[4]         image/buffer        Time for channel (if video or sound), in seconds</span></span><br><span class="line"><span class="comment">vec3        iChannelResolution[4]	image/buffer/sound	Input texture resolution for each channel</span></span><br><span class="line"><span class="comment">vec4        iMouse                  image/buffer        xy = current pixel coords (if LMB is down). zw = click pixel</span></span><br><span class="line"><span class="comment">sampler2D	iChannel&#123;i&#125;             image/buffer/sound	Sampler for input textures i</span></span><br><span class="line"><span class="comment">vec4        iDate                   image/buffer/sound	Year, month, day, time in seconds in .xyzw</span></span><br><span class="line"><span class="comment">float       iSampleRate             image/buffer/sound	The sound sample rate (typically 44100)</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="title">ShaderEffect</span> &#123;</span><br><span class="line">    <span class="attribute">id:</span><span class="string"> shader</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">//properties for shader</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">//not pass to shader</span></span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> vector3d defaultResolution</span>: Qt.vector3d(shader.width, shader.height, shader.width / shader.height)</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">calcResolution</span>(<span class="params">channel</span>) </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (channel) &#123;</span><br><span class="line">            <span class="keyword">return</span> Qt.vector3d(channel.width, channel.height, channel.width / channel.height);</span><br><span class="line">        &#125; <span class="title">else</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> defaultResolution;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//pass</span></span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> vector3d  iResolution</span>: defaultResolution</span><br><span class="line">    <span class="keyword">property</span><span class="string"> real       iTime</span>: <span class="number">0</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> real       iTimeDelta</span>: <span class="number">100</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> int        iFrame</span>: <span class="number">10</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> real       iFrameRate</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> vector4d   iMouse</span>;</span><br><span class="line">    <span class="keyword">property</span><span class="string"> var iChannel0</span>; <span class="comment">//only Image or ShaderEffectSource</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> var iChannel1</span>; <span class="comment">//only Image or ShaderEffectSource</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> var iChannel2</span>; <span class="comment">//only Image or ShaderEffectSource</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> var iChannel3</span>; <span class="comment">//only Image or ShaderEffectSource</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> var        iChannelTime</span>: [<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line">    <span class="keyword">property</span><span class="string"> var        iChannelResolution</span>: [calcResolution(iChannel0), calcResolution(iChannel1), calcResolution(iChannel2), calcResolution(iChannel3)]</span><br><span class="line">    <span class="keyword">property</span><span class="string"> vector4d   iDate</span>;</span><br><span class="line">    <span class="keyword">property</span><span class="string"> real       iSampleRate</span>: <span class="number">44100</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">//properties for Qml controller</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> alias hoverEnabled</span>: mouse.hoverEnabled</span><br><span class="line">    <span class="keyword">property</span><span class="string"> bool running</span>: <span class="literal">true</span></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">restart</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        shader.iTime = <span class="number">0</span></span><br><span class="line">        running = <span class="literal">true</span></span><br><span class="line">        timer1.restart()</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title">Timer</span> &#123;</span><br><span class="line">        <span class="attribute">id:</span><span class="string"> timer1</span></span><br><span class="line">        <span class="attribute">running</span>: shader.running</span><br><span class="line">        <span class="attribute">triggeredOnStart</span>: <span class="literal">true</span></span><br><span class="line">        <span class="attribute">interval</span>: <span class="number">16</span></span><br><span class="line">        <span class="attribute">repeat</span>: <span class="literal">true</span></span><br><span class="line">        <span class="attribute">onTriggered</span>: &#123;</span><br><span class="line">            shader.iTime += <span class="number">0.016</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title">Timer</span> &#123;</span><br><span class="line">        <span class="attribute">running</span>: shader.running</span><br><span class="line">        <span class="attribute">interval</span>: <span class="number">1000</span></span><br><span class="line">        <span class="attribute">onTriggered</span>: &#123;</span><br><span class="line">            <span class="keyword">var</span> <span class="built_in">date</span> = <span class="keyword">new</span> <span class="built_in">Date</span>();</span><br><span class="line">            shader.iDate.x = <span class="built_in">date</span>.getFullYear();</span><br><span class="line">            shader.iDate.y = <span class="built_in">date</span>.getMonth();</span><br><span class="line">            shader.iDate.z = <span class="built_in">date</span>.getDay();</span><br><span class="line">            shader.iDate.w = <span class="built_in">date</span>.getSeconds()</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title">MouseArea</span> &#123;</span><br><span class="line">        <span class="attribute">id:</span><span class="string"> mouse</span></span><br><span class="line">        <span class="attribute">anchors.fill</span>: <span class="built_in">parent</span></span><br><span class="line">        <span class="attribute">onPositionChanged</span>: &#123;</span><br><span class="line">            shader.iMouse.x = mouseX</span><br><span class="line">            shader.iMouse.y = mouseY</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="attribute">onClicked</span>: &#123;</span><br><span class="line">            shader.iMouse.z = mouseX</span><br><span class="line">            shader.iMouse.w = mouseY</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 如果环境是OpenGL ES2，默认的version是 version 110, 不需要写出来。</span></span><br><span class="line">    <span class="comment">// 比ES2更老的版本是ES 1.0 和 ES 1.1, 这种古董设备，还是不要玩Shader了吧。</span></span><br><span class="line">    <span class="comment">// ES2没有texture函数，要用旧的texture2D代替</span></span><br><span class="line">    <span class="comment">// 精度限定要写成float</span></span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> string gles2Ver</span>: <span class="string">"</span></span><br><span class="line"><span class="string">#define texture texture2D</span></span><br><span class="line"><span class="string">precision mediump float;</span></span><br><span class="line"><span class="string">"</span></span><br><span class="line">    <span class="comment">// 如果环境是OpenGL ES3，version是 version 300 es</span></span><br><span class="line">    <span class="comment">// ES 3.1 ES 3.2也可以。</span></span><br><span class="line">    <span class="comment">// ES3可以用in out 关键字，gl_FragColor也可以用out fragColor取代</span></span><br><span class="line">    <span class="comment">// 精度限定要写成float</span></span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> string gles3Ver</span>: <span class="string">"#version 300 es</span></span><br><span class="line"><span class="string">#define varying in</span></span><br><span class="line"><span class="string">#define gl_FragColor fragColor</span></span><br><span class="line"><span class="string">precision mediump float;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">out vec4 fragColor;</span></span><br><span class="line"><span class="string">"</span></span><br><span class="line">    <span class="comment">// 如果环境是OpenGL Desktop 3.x，version这里参考Qt默认的version 150。大部分Desktop设备应该都是150</span></span><br><span class="line">    <span class="comment">// 150 即3.2版本，第一个区分Core和Compatibility的版本。Core是核心模式，只有核心api以减轻负担。相应的Compatibility是兼容模式，保留全部API以兼容低版本。</span></span><br><span class="line">    <span class="comment">// 可以用in out 关键字，gl_FragColor也可以用out fragColor取代</span></span><br><span class="line">    <span class="comment">// 精度限定抹掉，用默认的。不抹掉有些情况下会报错，不能通用。</span></span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> string gl3Ver</span>: <span class="string">"#version 150</span></span><br><span class="line"><span class="string">#define varying in</span></span><br><span class="line"><span class="string">#define gl_FragColor fragColor</span></span><br><span class="line"><span class="string">#define lowp</span></span><br><span class="line"><span class="string">#define mediump</span></span><br><span class="line"><span class="string">#define highp</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">out vec4 fragColor;</span></span><br><span class="line"><span class="string">"</span></span><br><span class="line">    <span class="comment">// 如果环境是OpenGL Desktop 2.x，version这里就用2.0的version 110，即2.0版本</span></span><br><span class="line">    <span class="comment">// 2.x 没有texture函数，要用旧的texture2D代替</span></span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> string gl2Ver</span>: <span class="string">"#version 110</span></span><br><span class="line"><span class="string">#define texture texture2D</span></span><br><span class="line"><span class="string">"</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">property</span><span class="string"> string versionString</span>: &#123;</span><br><span class="line">        <span class="keyword">if</span> (Qt.platform.os === <span class="string">"android"</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (GraphicsInfo.majorVersion === <span class="number">3</span>) &#123;</span><br><span class="line">                <span class="built_in">console</span>.log(<span class="string">"android gles 3"</span>)</span><br><span class="line">                <span class="keyword">return</span> gles3Ver</span><br><span class="line">            &#125; <span class="title">else</span> &#123;</span><br><span class="line">                <span class="built_in">console</span>.log(<span class="string">"android gles 2"</span>)</span><br><span class="line">                <span class="keyword">return</span> gles2Ver</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="title">else</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (GraphicsInfo.majorVersion === <span class="number">3</span> ||GraphicsInfo.majorVersion === <span class="number">4</span>) &#123;</span><br><span class="line">                <span class="keyword">return</span> gl3Ver</span><br><span class="line">            &#125; <span class="title">else</span> &#123;</span><br><span class="line">                <span class="keyword">return</span> gl2Ver</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">vertexShader</span>: <span class="string">"</span></span><br><span class="line"><span class="string">              uniform mat4 qt_Matrix;</span></span><br><span class="line"><span class="string">              attribute vec4 qt_Vertex;</span></span><br><span class="line"><span class="string">              attribute vec2 qt_MultiTexCoord0;</span></span><br><span class="line"><span class="string">              varying vec2 qt_TexCoord0;</span></span><br><span class="line"><span class="string">              varying vec4 vertex;</span></span><br><span class="line"><span class="string">              void main() &#123;</span></span><br><span class="line"><span class="string">                  vertex = qt_Vertex;</span></span><br><span class="line"><span class="string">                  gl_Position = qt_Matrix * vertex;</span></span><br><span class="line"><span class="string">                  qt_TexCoord0 = qt_MultiTexCoord0;</span></span><br><span class="line"><span class="string">              &#125;"</span></span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> string forwardString</span>: versionString + <span class="string">"</span></span><br><span class="line"><span class="string">        varying vec2 qt_TexCoord0;</span></span><br><span class="line"><span class="string">        varying vec4 vertex;</span></span><br><span class="line"><span class="string">        uniform lowp   float qt_Opacity;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        uniform vec3   iResolution;</span></span><br><span class="line"><span class="string">        uniform float  iTime;</span></span><br><span class="line"><span class="string">        uniform float  iTimeDelta;</span></span><br><span class="line"><span class="string">        uniform int    iFrame;</span></span><br><span class="line"><span class="string">        uniform float  iFrameRate;</span></span><br><span class="line"><span class="string">        uniform float  iChannelTime[4];</span></span><br><span class="line"><span class="string">        uniform vec3   iChannelResolution[4];</span></span><br><span class="line"><span class="string">        uniform vec4   iMouse;</span></span><br><span class="line"><span class="string">        uniform vec4    iDate;</span></span><br><span class="line"><span class="string">        uniform float   iSampleRate;</span></span><br><span class="line"><span class="string">        uniform sampler2D   iChannel0;</span></span><br><span class="line"><span class="string">        uniform sampler2D   iChannel1;</span></span><br><span class="line"><span class="string">        uniform sampler2D   iChannel2;</span></span><br><span class="line"><span class="string">        uniform sampler2D   iChannel3;</span></span><br><span class="line"><span class="string">    "</span></span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> string startCode</span>: <span class="string">"</span></span><br><span class="line"><span class="string">        void main(void)</span></span><br><span class="line"><span class="string">        &#123;</span></span><br><span class="line"><span class="string">            mainImage(gl_FragColor, vec2(vertex.x, iResolution.y - vertex.y));</span></span><br><span class="line"><span class="string">        &#125;"</span></span><br><span class="line">    readonly <span class="keyword">property</span><span class="string"> string defaultPixelShader</span>: <span class="string">"</span></span><br><span class="line"><span class="string">        void mainImage(out vec4 fragColor, in vec2 fragCoord)</span></span><br><span class="line"><span class="string">        &#123;</span></span><br><span class="line"><span class="string">            fragColor = vec4(fragCoord, fragCoord.x, fragCoord.y);</span></span><br><span class="line"><span class="string">        &#125;"</span></span><br><span class="line">    <span class="keyword">property</span><span class="string"> string pixelShader</span>: <span class="string">""</span></span><br><span class="line">    <span class="attribute">fragmentShader</span>: forwardString + (pixelShader ? <span class="attribute">pixelShader</span> : defaultPixelShader) + startCode</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



    </div>
    
    <div class="reward" ontouchstart>
    <div class="reward-wrap">赏
        <div class="reward-box">
            
            <span class="reward-type">
                <img class="alipay" src="/img/zhifubao.jpg"><b>支付宝打赏</b>
            </span>
            
            
            <span class="reward-type">
                <img class="wechat" src="/img/weixin.jpg"><b>微信打赏</b>
            </span>
            
        </div>
    </div>
    <p class="reward-tip">
        为众人抱薪者,不可使其冻毙于霜雪
    </p>
</div>
    
    <div class="post-footer">
        <div>
            
            转载声明：
            文章采用<a href="http://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议</a>进行许可, 转载请注明出处 © <a href="https://jaredtao.github.io" target="_blank">武威的涛哥</a>
            
            
        </div>
        <div>
            
        </div>
    </div>
</article>
<div class="article-nav prev-next-wrap clearfix">
    
    <a href="/2019/07/06/%E7%8E%A9%E8%BD%ACQt(5)-%E7%90%86%E8%A7%A3%E4%BA%8B%E4%BB%B6%E5%BE%AA%E7%8E%AF/" class="pre-post btn btn-default" title='玩转Qt(5)-理解事件循环'>
        <i class="fa fa-angle-left fa-fw"></i><span class="hidden-lg">上一篇</span>
        <span class="hidden-xs">
            玩转Qt(5)-理解事件循环</span>
    </a>
    
    
    <a href="/2019/06/22/%E7%8E%A9%E8%BD%ACQml(15)-%E7%9D%80%E8%89%B2%E5%99%A8%E6%95%88%E6%9E%9CShaderEffect/" class="next-post btn btn-default" title='玩转Qml(15)-着色器效果ShaderEffect'>
        <span class="hidden-lg">下一篇</span>
        <span class="hidden-xs">
            玩转Qml(15)-着色器效果ShaderEffect</span><i class="fa fa-angle-right fa-fw"></i>
    </a>
    
</div>

<div id="comments">
    

<div id="vcomments" class="valine"></div>

<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src="/assets/valine.min.js"></script>

<script>
new Valine({
    av: AV,
    el: '#vcomments',
    appId: 'qegD4552u6FU9HoNDvRsonko-gzGzoHsz',
    appKey: 'eitB2FV5n2qyMHcDM7x6EQpt',
    placeholder: '说点什么吧',
    notify: false,
    verify: true,
    avatar: 'mm',
    meta: 'nick,mail'.split(','),
    pageSize: '10',
    path: window.location.pathname,
    lang: 'zh-CN'.toLowerCase()
})
</script>


</div>


                </main>
                
                    <aside id="article-toc" role="navigation" class="col-md-4">
    <div class="widget">
        <h3 class="title">
            文章目录
        </h3>
        
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#简介"><span class="toc-text">简介</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#源码"><span class="toc-text">源码</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#效果预览"><span class="toc-text">效果预览</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#穿云洞"><span class="toc-text">穿云洞</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#星球之光"><span class="toc-text">星球之光</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#蜗牛"><span class="toc-text">蜗牛</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#超级马里奥"><span class="toc-text">超级马里奥</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#关于ShaderToy"><span class="toc-text">关于ShaderToy</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#关于ShaderEffect"><span class="toc-text">关于ShaderEffect</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#ShaderToy原理"><span class="toc-text">ShaderToy原理</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#约定的变量"><span class="toc-text">约定的变量</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#glsl版本号"><span class="toc-text">glsl版本号</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#glsl版本兼容"><span class="toc-text">glsl版本兼容</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#ShaderToy适配"><span class="toc-text">ShaderToy适配</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#TaoShaderToy"><span class="toc-text">TaoShaderToy</span></a></li></ol>
        
    </div>
</aside>
                
            </div>
        </div>
    </section>
    <footer class="main-footer">
    <div class="container">
        <div class="row">
        </div>
    </div>
</footer>
<a id="back-to-top" class="icon-btn hide">
    <i class="fa fa-chevron-up"></i>
</a>
    <div class="copyright">
    <div class="container">
        <div class="row">
            <div class="col-sm-12">
                <div class="busuanzi">
    
    访问量:
    <strong id="busuanzi_value_site_pv">
        <i class="fa fa-spinner fa-spin"></i>
    </strong>
    &nbsp; | &nbsp;
    访客数:
    <strong id="busuanzi_value_site_uv">
        <i class="fa fa-spinner fa-spin"></i>
    </strong>
    
</div>
            </div>
            <div class="col-sm-12">
                <span>Copyright &copy;
                    2019
                    
                </span> |
                <span>
                    Powered by <a href="//hexo.io" class="copyright-links" target="_blank" rel="nofollow">Hexo</a>
                </span> |
                <span>
                    Theme by <a href="//github.com/shenliyang/hexo-theme-snippet.git" class="copyright-links" target="_blank" rel="nofollow">Snippet</a>
                </span>
            </div>
        </div>
    </div>
</div>



<script src="/assets/tagcanvas.min.js?rev=2.9.js"></script>

<script>
var tagOption = {
    textColour: '#444', // 字体颜色
    outlineMethod: 'block', // 选中模式
    outlineColour: '#FFDAB9', // 选中模式的颜色
    interval: 30 || 30, // 动画帧之间的时间间隔，值越大，转动幅度越大
    textHeight: 13,
    outlineRadius: 3,
    freezeActive: true || '', // 选中的标签是否继续滚动
    frontSelect: true || '', // 不选标签云后部的标签
    initial: [0.1, -0.1],
    depth: 0.5,
    decel: 0.95,
    maxSpeed: 0.03,
    reverse: true || '', // 是否反向触发
    fadeIn: 500, // 进入动画时间
    wheelZoom: false || '' // 是否启用鼠标滚轮
}
TagCanvas.Start('tag-cloud-3d', '', tagOption);
</script>


<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>


<script src="/js/app.js?rev=@@hash.js"></script>

</body>
</html>